﻿using Sgr.Domain.Entities;

namespace Sgr.EventBus.RelayBoxs.Domain
{
    /// <summary>
    /// 表示存储在发件箱（Outbox）中的消息实体。
    /// 该实体用于实现可靠的事件驱动架构中的事件发布，
    /// 确保即使系统发生故障，事件也不会丢失，最终能够被可靠地投递。
    /// </summary>
    public class OutboxMessage : Entity<long>, IAggregateRoot
    {
        /// <summary>
        /// 初始化一个 <see cref="OutboxMessage"/> 类型的新实例。
        /// </summary>
        private OutboxMessage()
        {
        }

        /// <summary>
        /// 初始化一个 <see cref="OutboxMessage"/> 类型的新实例。
        /// </summary>
        /// <param name="messageTopic"></param>
        /// <param name="messageType"></param>
        /// <param name="messageId"></param>
        /// <param name="payload"></param>
        public OutboxMessage(
            string messageTopic,
            string messageType,
            string messageId,
            string payload)
        {
            MessageTopic = messageTopic;
            MessageType = messageType;
            MessageId = messageId;
            Payload = payload;
            OccurredOnUtc = DateTime.UtcNow;
            NextOnUtc = DateTime.UtcNow;
        }

        /// <summary>
        /// 消息要发送到的主题（Topic），通常对应消息队列中的 Topic 或 Channel。
        /// </summary>
        public string MessageTopic { get; set; } = string.Empty;

        /// <summary>
        /// 消息的类型，用于标识消息内容的结构或业务含义，例如 "OrderCreated"、"PaymentPaid" 等。
        /// </summary>
        public string MessageType { get; set; } = string.Empty;

        /// <summary>
        /// 消息的唯一 ID，通常是业务系统生成的 GUID 或唯一字符串，
        /// 用于在消息系统中追踪和去重。
        /// </summary>
        public string MessageId { get; set; } = string.Empty;

        /// <summary>
        /// 消息的实际内容（Payload），通常是 JSON 或其他序列化格式的业务数据。
        /// </summary>
        public string Payload { get; set; } = string.Empty;

        /// <summary>
        /// 消息产生的时间（UTC 时间），表示该事件在业务系统中发生的时间点。
        /// </summary>
        public DateTime OccurredOnUtc { get; set; } = DateTime.UtcNow;

        /// <summary>
        /// 下一次尝试投递的时间（UTC 时间）。
        /// 通过该字段来控制后台定时 Dispatched 时的时机（满足当前时间 >= NextOnUtc 则表示等待投递）。
        /// </summary>
        public DateTime NextOnUtc { get; set; }

        /// <summary>
        /// 消息当前所处的状态，默认为 Pending（待处理）。
        /// 常见状态包括：Pending（待处理）、Dispatched（已投递）、Failed（失败）等。
        /// </summary>
        public OutboxStatus Status { get; set; } = OutboxStatus.Pending;

        /// <summary>
        /// 消息实际被投递出去的时间（UTC 时间），如果为 null 表示尚未投递。
        /// </summary>
        public DateTime? DispatchedOnUtc { get; set; }

        /// <summary>
        /// 当前消息已经尝试投递的次数，用于控制重试策略和防止无限重试。
        /// </summary>
        public int RetryCount { get; set; } = 0;

        /// <summary>
        /// 上一次投递失败时的错误信息，用于排查问题和日志记录。
        /// 如果投递成功或尚未失败，则为 null。
        /// </summary>
        public string? LastError { get; set; }
    }
}